package jmine.tec.report.impl;

import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;

import jmine.tec.report.api.RendererParameters;
import jmine.tec.report.api.Report;
import jmine.tec.report.api.ReportElement;
import jmine.tec.report.api.ReportFooter;
import jmine.tec.report.api.ReportHeader;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Implementação de report composto
 * 
 * @author lundberg
 */
public class ReportImpl implements Report, Serializable {

    private static final Log LOG = LogFactory.getLog(ReportImpl.class);

    private ReportHeader header;

    private List<ReportElement> elements;

    private RendererParameters parameters;

    private ReportFooter footer;

    /**
     * Construtor.
     */
    public ReportImpl() {
        this.header = new ReportHeaderImpl();
        this.elements = new LinkedList<ReportElement>();
        this.parameters = new RendererParametersImpl();
        this.footer = new ReportFooterImpl();
    }

    /**
     * Adiciona um componente ao report composto
     * 
     * @param element component
     */
    public void addElement(ReportElement element) {
        element.getParameters().setParent(this.parameters);
        this.assignUniqueElementId(element);
        this.elements.add(element);
    }

    /**
     * Designa um id único ao elemento de relatório que será adicionado, caso necessário.
     * 
     * @param element element
     */
    private void assignUniqueElementId(ReportElement element) {
        if (this.isUniqueElementId(element.getReportId())) {
            return;
        }
        LOG.warn("ReportElement não possui ID único: " + element.getReportId());
        int i = 0;
        String newReportId;
        do {
            newReportId = element.getReportId() + "_" + i++;
        } while (!this.isUniqueElementId(newReportId));
        element.setReportId(newReportId);
    }

    /**
     * Verifica se já existe ReportElement com o id dado
     * 
     * @param reportId reportId
     * @return boolean
     */
    private boolean isUniqueElementId(String reportId) {
        for (ReportElement element : this.elements) {
            if (element.getReportId().equals(reportId)) {
                return false;
            }
        }
        return true;
    }

    /**
     * {@inheritDoc}
     */
    public List<ReportElement> getElements() {
        return this.elements;
    }

    /**
     * {@inheritDoc}
     */
    public ReportHeader getHeader() {
        return this.header;
    }

    /**
     * {@inheritDoc}
     */
    public RendererParameters getParameters() {
        return this.parameters;
    }

    /**
     * {@inheritDoc}
     */
    public ReportFooter getFooter() {
        return this.footer;
    }
}
